<?php


require __DIR__.'/../lib/User.php';
require __DIR__.'/../lib/Article.php';
$pdo = require __DIR__.'/../lib/db.php';
class Restful
{
	private $_user;
	private $_article;
	private $_requestMethod;		//请求方法
	private $_resourceName;			//请求的资源名称
	private $_id;					//请求的资源ID
	private $_allowResources = ['users' , 'articles'];		//允许请求的资源
	private $_allowRequestMethods = ['GET' , 'POST' , 'PUT' , 'DELETE' , 'OPTIONS'];		//允许请求的方法
	//返回的状态码
	private $_statusCodes = [
		200=>'ok',
		204=>'No Content',
		400=>'Bad Request',
		401=>'Unauthorized',
		403=>'Forbidden',
		404=>'Not Found',
		405=>'Method Not Allowed',
		500=>'Server Internal Error'
	];
	public function __construct(User $_user , Article $_article)
	{
		$this->_user = $_user;
		$this->_article = $_article;
	}

	//只有一个公共的入口
	public function run()
	{
		try{
			$this->_setupRequestMethod();
			$this->_setupResource();
			if($this->_resourceName == 'users'){
				return $this->_json($this->_handleUser());
			} else{
				return $this->_json($this->_handleArticle());
			}
		} catch(Exception $e){
			$this->_json(['error'=>$e->getMessage()], $e->getCode());
		}
	}

	//初始化请求方法
	private function _setupRequestMethod()
	{
		$this->_requestMethod = $_SERVER['REQUEST_METHOD'];
		if(!in_array($this->_requestMethod, $this->_allowRequestMethods)){
			throw new Exception("不允许的请求方法", 405);
			
		}
	}

	//初始化请求资源
	private function _setupResource()
	{
		$path = $_SERVER['REDIRECT_PATH_INFO'];			//不知道为什么这里不是PATH_INFO，而是重定向REDIRECT_PATH_INFO
		$params = explode('/', $path);
		$this->_resourceName = $params[0];
		if(!in_array($this->_resourceName, $this->_allowResources)){
			throw new Exception("请求资源不被允许", 400);
		}
		if(!empty($params[1])){
			$this->_id = $params[1];
		}
	}

	//json格式输出
	private function _json($array , $code = 0)
	{
		//没有响应体，但是没出错
		if($array === null && $code === 0){
			$code = 204;
		}
		//有响应体
		if($array !== null && $code === 0){
			$code = 200;
		}
		header("HTTP/1.1 ".$code." ".$this->_statusCodes[$code]."");
		header('Content-Type:application/json;charset=utf-8');
		if($array !== null ){
			echo json_encode($array , JSON_UNESCAPED_UNICODE);
		}
		exit();
	}

	//请求用户
	private function _handleUser()
	{

		//用户只允许注册方法
		if($this->_requestMethod != 'POST'){
			throw new Exception("请求方法不被允许", 405);
		}
		$body = $this->_getBodyParams();

		if(empty($body['username'])){
			throw new Exception("用户名不能为空",400);
		}
		if(empty($body['password'])){
			throw new Exception("密码不能为空",400);
		}
		
		return $this->_user->register($body['username'] , $body['password']);
	}

	//请求文章资源
	private function _handleArticle()
	{
		switch ($this->_requestMethod) {
			case 'POST':
				return $this->_handleArticleCreate();
				break;
			case 'PUT':
				return $this->_handleArticleEdit();
				break;
			case 'DELETE':
				return $this->_handleArticleDelete();
				break;
			case 'GET':
				if(empty($this->_id)){
					return $this->_handleArticleList();
				} else{
					return $this->_handleArticleView();
				}
				break;
			default:
				throw new Exception("不允许的请求方法", 405);
				break;
		}
	}

	//创建文章
	private function _handleArticleCreate()
	{
		$body = $this->_getBodyParams();
		if(empty($body['title'])){
			throw new Exception("文章标题不能为空", 400);
		}
		if(empty($body['content'])){
			throw new Exception("文章内容不能为空", 400);
		}
		$user = $this->_userlogin($_SERVER['PHP_AUTH_USER'] , $_SERVER['PHP_AUTH_PW']);
		try {
			$article = $this->_article->create($body['title'] , $body['content'] , $user['userId']);
			return $article;
		} catch (Exception $e) {
			if(!in_array($e->getCode(),
				[
					ErrorCode::ARTICLE_TITLE_CANNOT_EMPTY,
					ErrorCode::ARTICLE_CONTENT_CANNOT_EMPTY
				]
			)){
				throw new Exception($e->getMessage(), 400);
			}
			throw new Exception($e->getMessage(), 500);			
		}
	}

	//文章编辑
	private function _handleArticleEdit()
	{
		$user = $this->_userlogin($_SERVER['PHP_AUTH_USER'] , $_SERVER['PHP_AUTH_PW']);
		try {
			$article = $this->_article->view($this->_id);  //获取到需要编辑的文章
			if($article['userId'] != $user['userId']){
				throw new Exception("您无权编辑此文章", 403);
			}
			$body = $this->_getBodyParams();
			$title = empty($body['title'])?$article['title']:$body['title'];
			$content = empty($body['content'])?$article['content']:$body['content'];
			//如果文章标题和内容和之前 都一样，就直接返回原来的文章，不作修改
			if($title == $article['title'] && $content == $article['content']){
				return $article;
			}
			return $this->_article->edit($article['articleId'] , $title , $content , $user['userId']);
		} catch (Exception $e) {
			//如果是自己设置的状态码都是小于100的，就按404或400状态码返回
			if($e->getCode()<100){
				if($e->getCode() == ErrorCode::ARTICLE_NOT_FOUND){
					throw new Exception($e->getMessage(), 404);
				} else {
					throw new Exception($e->getMessage(), 400);
				}
			} else{
				throw new Exception($e->getMessage(),$e->getCode());
			}
		}

	}

	//删除文章
	private function _handleArticleDelete()
	{
		$user = $this->_userlogin($_SERVER['PHP_AUTH_USER'] , $_SERVER['PHP_AUTH_PW']);
		try {
			$article = $this->_article->view($this->_id);  //获取到需要编辑的文章
			if($article['userId'] != $user['userId']){
				throw new Exception("您无权编辑此文章", 403);
			}
			$this->_article->delete($article['articleId'] , $user['userId']);
			return null;
		} catch (Exception $e) {
			//如果是自己设置的状态码都是小于100的，就按404或400状态码返回
			if($e->getCode()<100){
				if($e->getCode() == ErrorCode::ARTICLE_NOT_FOUND){
					throw new Exception($e->getMessage(), 404);
				} else {
					throw new Exception($e->getMessage(), 400);
				}
			} else{
				throw new Exception($e->getMessage(),$e->getCode());
			}
		}
	}

	//获取文章列表
	private function _handleArticleList()
	{
	
		$user = $this->_userlogin($_SERVER['PHP_AUTH_USER'] , $_SERVER['PHP_AUTH_PW']);
		$page = isset($_GET['page'])?$_GET['page']:1;			//这里$_GET没有数据，不知道为什么
		$size = isset($_GET['size'])?$_GET['size']:10;
		if($size > 100){
			throw new Exception("分页大小最大100", 400);
		}
		return $this->_article->getList($user['userId'] , $page , $size);
	}

	//根据id获取单个文章
	private function _handleArticleView()
	{
		try {
			return $this->_article->view($this->_id);
		} catch (Exception $e) {
			if($e->getCode() == ErrorCode::ARTICLE_NOT_FOUND){
					throw new Exception($e->getMessage(), 404);
				} else {
					throw new Exception($e->getMessage(), 500);
				}
		}
	}

	//用户登录
	private function _userlogin($PHP_AUTH_USER , $PHP_AUTH_PW)
	{
		try{
			return $this->_user->login($PHP_AUTH_USER , $PHP_AUTH_PW);
		} catch(Exception $e){
			if(in_array($e->getCode(), 
				[
					ErrorCode::USERNAME_CANNOT_EMPTY,
					ErrorCode::PASSWORD_CANNOT_EMPTY,
					ErrorCode::USERNAME_OR_PASSWORD_INVALID
				])){
				throw new Exception($e->getMessage(), 400);
			}
			throw new Exception($e->getMessage(), 500);
			
		}

	}

	//获取请求体参数
	private function _getBodyParams()
	{
		$raw = file_get_contents('php://input');
		if(empty($raw)){
			throw new Exception("请求参数错误", 400);
		}

		return json_decode($raw,true);
	}

}
$article = new Article($pdo);
$user = new User($pdo);
$restful = new Restful($user , $article);
$restful->run();